<template>
  <el-card class="box-card">
    <!-- 新增品牌按钮 -->
    <el-button type="primary" icon="Plus" @click="addTradeMark">添加品牌</el-button>
    <!-- 表格组件—展示数据 -->
    <el-table :data="trademarkArr" style="margin: 10px 0px" border>
      <el-table-column type="index" label="序号" width="80px" align="center">
      </el-table-column>
      <!-- table-column：默认是使用div展示的数据的，此处使用插槽 -->
      <el-table-column label="品牌名称">
        <template #="{ row }">
          <pre style="color: brown">{{ row.tmName }}</pre>
        </template>
      </el-table-column>
      <el-table-column label="品牌LOGO">
        <template #="{ row }">
          <img
            :src="row.logoUrl"
            style="width: 100px; height: 100px; border: 1px solid white"
          />
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template #="{ row }">
          <el-button
            size="small"
            type="primary"
            icon="Edit"
            @click="updateTrademark(row)"
          ></el-button>
          <el-popconfirm
            :title="`确认要删除【${row.tmName}】吗?`"
            width="250"
            @confirm="removeTrademark(row.id)"
          >
            <template #reference>
              <el-button size="small" type="danger" icon="Delete"></el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <!-- 
      分页器
      v-model实现了父子组件传递的数据的同步，会自动收集数据的变化 
        故当前页改变的事件回调直接是 getHasTradeMark方法
    -->
    <el-pagination
      background
      v-model:current-page="currentPage"
      :page-sizes="[10, 20, 50]"
      v-model:page-size="pageSize"
      layout=" prev, pager, next, jumper, ->, sizes, total"
      :total="total"
      @current-change="getHasTradeMark"
      @size-change="changePageSize"
    />
  </el-card>
  <!-- 对话框组件：添加品牌和修改品牌时使用 -->
  <!-- dialogFormVisible 控制对话框的显示和隐藏 -->
  <el-dialog v-model="dialogFormVisible" :title="title" width="500" @closed="closeDialog">
    <el-form
      ref="formRef"
      class="formContainer"
      :model="trademarkFormData"
      :rules="rules"
      style="width: 80%"
      label-width="104px"
      label-position="left"
    >
      <el-form-item label="品牌名称" prop="tmName">
        <el-input v-model="trademarkFormData.tmName" placeholder="请输入品牌名称" />
      </el-form-item>
      <el-form-item label="品牌LOGO" prop="logoUrl">
        <!-- 
          action： 图片上传的服务器地址
          auto-upload：值默认是true，自动上传
        -->
        <el-upload
          class="avatar-uploader"
          action="/api/admin/product/fileUpload"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload"
        >
          <img
            v-if="trademarkFormData.logoUrl"
            :src="trademarkFormData.logoUrl"
            class="avatar"
          />
          <el-icon v-else class="avatar-uploader-icon">
            <Plus />
          </el-icon>
        </el-upload>
        <span class="tip-info">图片只支持png、jpg、gif样式</span>
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button type="primary" @click="confirm"> 确定 </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, computed } from "vue";
import {
  reqHasTradeMark,
  reqAddOrEditTradeMark,
  reqDeleteTrademark,
} from "@/api/product/trademark";
import { onMounted } from "vue";
import type { Records, HasTradeMark, TradeMark } from "@/api/product/trademark/types";
import type { FormInstance, UploadProps } from "element-plus";
import { ElMessage } from "element-plus";

// 当前页码
const currentPage = ref(1);
// 页面展示数据的条数
const pageSize = ref(10);
// 已有品牌总数
let total = ref(0);
// 已有品牌的数据
const trademarkArr = ref<Records>([]);
// 控制对话框的显示和隐藏
const dialogFormVisible = ref(false);
// 对话框标题
let title = computed(() => {
  return trademarkFormData.id ? "修改品牌" : "添加品牌";
});
// 表单实例
const formRef = ref<FormInstance>();
// 表单数据
const trademarkFormData = reactive<TradeMark>({
  tmName: "",
  logoUrl: "",
});
// 品牌名称自定义校验规则
const validatorTmName = (rules: any, value: any, callback: any) => {
  if (value.trim().length >= 2) {
    callback();
  } else {
    callback(new Error("品牌名称需大于等于两位"));
  }
};
// 品牌logo自定义校验规则
const validatorLogo = (rules: any, value: any, callback: any) => {
  if (value) {
    // 图片上传
    callback();
  } else {
    // 图片未上传
    callback(new Error("请上传品牌LOGO"));
  }
};
// 表单校验规则对象
const rules = {
  tmName: [{ required: true, trigger: "blur", validator: validatorTmName }],
  logoUrl: [{ required: true, validator: validatorLogo }],
};

/**
 * 获取已有品牌的数据
 *  1. pager参数在当前页面改变时，会被传入当前页码
 *  2. 而在页面显示个数变化时，则没有传入参数，使用默认值
 */
const getHasTradeMark = async (pager = 1) => {
  currentPage.value = pager;
  let result: HasTradeMark = await reqHasTradeMark(currentPage.value, pageSize.value);
  if (result.code === 200) {
    total.value = result.data?.total;
    trademarkArr.value = result.data?.records;
  }
};
onMounted(() => {
  getHasTradeMark();
});
// 页面显示数据个数变化的回调
const changePageSize = () => {
  // 使用了 v-model，页面显示个数变化后会自动收集，不需要手动赋值
  getHasTradeMark();
};
// 添加品牌按钮的回调
const addTradeMark = () => {
  // 对话框显示
  dialogFormVisible.value = true;
  /* 数据清空操作，写在了对话框的closed回调中，写在这里也可以 
  // 若使用 trademarkFormData.id 来进行判断，则id也需要置空
  trademarkFormData.id = undefined;
  trademarkFormData.tmName = "";
  trademarkFormData.logoUrl = ""; */
};
// 修改品牌按钮的回调
const updateTrademark = (row: TradeMark) => {
  // 对话框显示
  dialogFormVisible.value = true;
  // 回传品牌数据
  Object.assign(trademarkFormData, row);
};
// 图片上传之前的回调
const beforeAvatarUpload: UploadProps["beforeUpload"] = (rawFile) => {
  // 可以用来对图片的大小和类型进行限制
  // 验证成功的话，图片就上传到指定的服务器上了
  if (
    rawFile.type === "image/png" ||
    rawFile.type === "image/jpeg" ||
    rawFile.type === "image/gif"
  ) {
    if (rawFile.size / 1024 / 1024 < 4) {
      return true;
    } else {
      ElMessage.error("上传文件的大小不能超过3M");
      return false;
    }
  } else {
    ElMessage.error("上传文件的格式只能是PNG|JPG|GIF");
    return false;
  }
};
// 图片上传成功的回调，两个参数
// response：上传图片成功后，服务器返回的数据
// uploadFile：图片本身的相关数据（如：图片大小等）
const handleAvatarSuccess: UploadProps["onSuccess"] = (response, uploadFile) => {
  // 收集上传品牌图片的地址，用于新增品牌
  trademarkFormData.logoUrl = response.data;
  ElMessage({
    type: "success",
    message: "图片上传成功",
  });
  // 图片上传成功，清除提示信息
  formRef.value?.clearValidate("logoUrl");
};
// 对话框确定按钮的回调
const confirm = () => {
  // 判断校验规则是否通过
  formRef.value?.validate(async (valid) => {
    if (valid) {
      // 发送请求添加品牌
      let result = await reqAddOrEditTradeMark(trademarkFormData);
      if (result.code === 200) {
        // 品牌新增成功
        dialogFormVisible.value = false;
        ElMessage({
          type: "success",
          message: `${title.value}成功`,
        });
        getHasTradeMark(title.value === "修改品牌" ? currentPage.value : 1);
      } else {
        ElMessage.error(`${title.value}失败`);
        dialogFormVisible.value = false;
      }
    }
  });
};
// 对话框关闭的回调
const closeDialog = () => {
  // 对话框中的提示信息，关闭之前统一清空
  // 若使用 trademarkFormData.id 来进行判断，则id也需要置空
  trademarkFormData.id = undefined;
  trademarkFormData.tmName = "";
  trademarkFormData.logoUrl = "";
  // 注意：首次加载页面时，dialog没有渲染，获取不到实例信息
  // 1、使用可选连?.进行判断，实例存在再去调用方法
  // 2、使用 nextTick 方法
  // 但这里不需要，方法调用时，对话框已存在
  formRef.value?.clearValidate(["tmName", "logoUrl"]);
};
// 确认删除品牌按钮的回调
const removeTrademark = async (id: number) => {
  // 发送请求删除品牌
  let result: any = await reqDeleteTrademark(id);
  if (result.code === 200) {
    // 删除成功
    ElMessage({
      type: "success",
      message: "删除品牌成功",
    });
    // 再次获取已有的品牌数据
    // 注意：当前页展示的数据若是一个，删完后回到上一页；若大于一个，则留在当前页
    getHasTradeMark(
      trademarkArr.value.length > 1 ? currentPage.value : currentPage.value - 1
    );
  } else {
    ElMessage.error("删除品牌失败");
  }
};
</script>

<script lang="ts">
export default {
  name: "TradeMark",
};
</script>

<style scoped lang="scss">
.formContainer {
  // 使用深度选择器，修改子组件的样式
  &:deep(.el-form-item__label) {
    padding: 0 12px 0 12px;
  }
  .tip-info {
    color: red;
    font-size: 12px;
    font-weight: bold;
    display: block;
    &::before {
      color: var(--el-color-danger);
      content: "*";
      margin-right: 4px;
    }
  }
  .avatar-uploader {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);

    &:hover {
      border-color: var(--el-color-primary);
    }

    .avatar {
      width: 178px;
      height: 178px;
      display: block;
    }

    .avatar-uploader-icon {
      font-size: 28px;
      color: #8c939d;
      width: 178px;
      height: 178px;
      text-align: center;
    }
  }
}
</style>
